package com.authsphere.security.web.handler;

import com.authsphere.plugin.api.AuthSphereAfterPlugin;
import com.authsphere.plugin.api.AuthSphereAfterPluginChain;
import com.authsphere.plugin.api.AuthSphereBeforePlugin;
import com.authsphere.plugin.api.AuthSphereBeforePluginChain;
import com.authsphere.plugin.api.AuthSpherePlugin;
import com.authsphere.plugin.api.AuthSpherePluginChain;
import com.authsphere.plugin.api.WebExchange;
import com.google.common.collect.Maps;

import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

/**
 * @program: AuthSphere
 * @description:
 * @author: YuKai Fan
 * @create: 2025/3/26 09:53
 **/
public class AuthSphereAuthenticationHandler implements AuthenticationHandler {

    private final List<AuthSphereBeforePlugin> beforePlugins;

    private final List<AuthSphereAfterPlugin> afterPlugins;

    public AuthSphereAuthenticationHandler(List<AuthSphereBeforePlugin> beforePlugins, List<AuthSphereAfterPlugin> afterPlugins) {
        this.beforePlugins = beforePlugins;
        this.afterPlugins = afterPlugins;
    }

    @Override
    public void handle(WebExchange exchange, HandleType handleType) {
        getChain(handleType).execute(exchange);
    }

    private AuthSpherePluginChain getChain(HandleType handleType) {
        if (handleType == HandleType.AFTER) {
            return new DefaultAuthSphereAfterPluginChain(this.afterPlugins);
        } else {
            return new DefaultAuthSphereBeforePluginChain(this.beforePlugins);
        }
    }

    private static class DefaultAuthSphereBeforePluginChain implements AuthSphereBeforePluginChain {
        private int index;
        private final List<AuthSphereBeforePlugin> plugins;

        DefaultAuthSphereBeforePluginChain(List<AuthSphereBeforePlugin> plugins) {
            this.plugins = plugins;
        }

        @Override
        public void execute(WebExchange exchange) {
            if (this.index < plugins.size()) {
                if (exchange.isAbort()) {
                    return;
                }
                AuthSphereBeforePlugin plugin = plugins.get(this.index++);
                boolean skip = plugin.skip(exchange);
                if (skip) {
                    this.execute(exchange);
                } else {
                    plugin.execute(exchange, this);
                }
            }
        }
    }

    private static class DefaultAuthSphereAfterPluginChain implements AuthSphereAfterPluginChain {
        private int index;
        private final List<AuthSphereAfterPlugin> plugins;

        DefaultAuthSphereAfterPluginChain(List<AuthSphereAfterPlugin> plugins) {
            this.plugins = plugins;
        }

        @Override
        public void execute(WebExchange exchange) {
            if (this.index < plugins.size()) {
                if (exchange.isAbort()) {
                    return;
                }
                AuthSphereAfterPlugin plugin = plugins.get(this.index++);
                boolean skip = plugin.skip(exchange);
                if (skip) {
                    this.execute(exchange);
                } else {
                    plugin.execute(exchange, this);
                }
            }
        }
    }
}
